μλ°μ€ν¬λ¦½νΈ λ°μ½λ μ΄ν°μ λν μ¬μΈ΅ λΆμ. λ¬Έλ², λ©νλ°μ΄ν° νλ‘κ·Έλλ° μ¬μ© μ¬λ‘, λͺ¨λ² μ¬λ‘, μ½λ μ μ§λ³΄μμ±μ λ―ΈμΉλ μν₯μ νꡬν©λλ€. μ€μ©μ μΈ μμ μ ν₯ν κ³ λ €μ¬νμ ν¬ν¨ν©λλ€.
μλ°μ€ν¬λ¦½νΈ λ°μ½λ μ΄ν°: λ©νλ°μ΄ν° νλ‘κ·Έλλ° κ΅¬ννκΈ°
μλ°μ€ν¬λ¦½νΈ λ°μ½λ μ΄ν°λ ν΄λμ€, λ©μλ, μμ± λ° λ§€κ°λ³μμ λμμ μμ νκ³ λ©νλ°μ΄ν°λ₯Ό μ μΈμ μ΄κ³ μ¬μ¬μ© κ°λ₯ν λ°©μμΌλ‘ μΆκ°ν μ μλ κ°λ ₯ν κΈ°λ₯μ λλ€. μ΄λ ECMAScript νμ€ νλ‘μΈμ€μμ 3λ¨κ³ μ μμ΄λ©°, μ체μ μΌλ‘ (μ½κ° λ€λ₯Έ) ꡬνμ κ°μ§ νμ μ€ν¬λ¦½νΈ(TypeScript)μμ λ리 μ¬μ©λ©λλ€. μ΄ κΈμμλ μλ°μ€ν¬λ¦½νΈ λ°μ½λ μ΄ν°μ λν ν¬κ΄μ μΈ κ°μλ₯Ό μ 곡νλ©°, λ©νλ°μ΄ν° νλ‘κ·Έλλ°μμμ μν μ μ΄μ μ λ§μΆκ³ μ€μ μμ λ₯Ό ν΅ν΄ μ¬μ©λ²μ μ€λͺ ν©λλ€.
μλ°μ€ν¬λ¦½νΈ λ°μ½λ μ΄ν°λ 무μμΈκ°?
λ°μ½λ μ΄ν°λ κ°μ²΄μ ꡬ쑰λ₯Ό λ³κ²½νμ§ μκ³ κΈ°λ₯μ ν₯μμν€κ±°λ μμ νλ λμμΈ ν¨ν΄μ
λλ€. μλ°μ€ν¬λ¦½νΈμμ λ°μ½λ μ΄ν°λ ν΄λμ€, λ©μλ, μ κ·Όμ, μμ± λλ λ§€κ°λ³μμ λΆμΌ μ μλ νΉλ³ν μ’
λ₯μ μ μΈμ
λλ€. @ κΈ°νΈλ₯Ό μ¬μ©νλ©°, κ·Έ λ€μ λ°μ½λ μ΄νΈλ μμκ° μ μλ λ μ€νλ ν¨μκ° λ°λ¦
λλ€.
λ°μ½λ μ΄ν°λ₯Ό λ°μ½λ μ΄νΈλ μμλ₯Ό μ λ ₯μΌλ‘ λ°μ μμ λ λ²μ μ λ°ννκ±°λ, μ΄λ₯Ό κΈ°λ°μΌλ‘ μ΄λ€ λΆμ ν¨κ³Όλ₯Ό μννλ ν¨μλΌκ³ μκ°νλ©΄ λ©λλ€. μ΄λ μλ³Έ ν΄λμ€λ ν¨μλ₯Ό μ§μ λ³κ²½νμ§ μκ³ κΈ°λ₯μ μΆκ°νλ κΉλνκ³ μ°μν λ°©λ²μ μ 곡ν©λλ€.
μ£Όμ κ°λ :
- λ°μ½λ μ΄ν° ν¨μ:
@κΈ°νΈκ° μμ λΆλ ν¨μμ λλ€. λ°μ½λ μ΄νΈλ μμμ λν μ 보λ₯Ό λ°μ μμ ν μ μμ΅λλ€. - λ°μ½λ μ΄νΈλ μμ: λ°μ½λ μ΄ν°κ° μ μ©λ ν΄λμ€, λ©μλ, μ κ·Όμ, μμ± λλ λ§€κ°λ³μμ λλ€.
- λ©νλ°μ΄ν°: λ°μ΄ν°λ₯Ό μ€λͺ νλ λ°μ΄ν°μ λλ€. λ°μ½λ μ΄ν°λ μ’ μ’ λ©νλ°μ΄ν°λ₯Ό μ½λ μμμ μ°κ²°νλ λ° μ¬μ©λ©λλ€.
λ¬Έλ² λ° κ΅¬μ‘°
λ°μ½λ μ΄ν°μ κΈ°λ³Έ λ¬Έλ²μ λ€μκ³Ό κ°μ΅λλ€:
@decorator
class MyClass {
// ν΄λμ€ λ©€λ²
}
μ¬κΈ°μ @decoratorλ λ°μ½λ μ΄ν° ν¨μμ΄κ³ MyClassλ λ°μ½λ μ΄νΈλ ν΄λμ€μ
λλ€. λ°μ½λ μ΄ν° ν¨μλ ν΄λμ€κ° μ μλ λ νΈμΆλλ©° ν΄λμ€ μ μμ μ κ·Όνκ³ μμ ν μ μμ΅λλ€.
λ°μ½λ μ΄ν°λ μΈμλ₯Ό λ°μ μλ μμΌλ©°, μ΄λ λ°μ½λ μ΄ν° ν¨μ μ체μ μ λ¬λ©λλ€:
@loggable(true, "Custom Message")
class MyClass {
// ν΄λμ€ λ©€λ²
}
μ΄ κ²½μ°, loggableμ μΈμλ₯Ό λ°μ μ€μ λ°μ½λ μ΄ν° ν¨μλ₯Ό λ°ννλ λ°μ½λ μ΄ν° ν©ν 리 ν¨μμ
λλ€. μ΄λ₯Ό ν΅ν΄ λ μ μ°νκ³ μ€μ κ°λ₯ν λ°μ½λ μ΄ν°λ₯Ό λ§λ€ μ μμ΅λλ€.
λ°μ½λ μ΄ν°μ μ’ λ₯
λ°μ½λ μ΄ν°λ 무μμ λ°μ½λ μ΄νΈνλλμ λ°λΌ μ¬λ¬ μ’ λ₯κ° μμ΅λλ€:
- ν΄λμ€ λ°μ½λ μ΄ν°: ν΄λμ€μ μ μ©λ©λλ€.
- λ©μλ λ°μ½λ μ΄ν°: ν΄λμ€ λ΄μ λ©μλμ μ μ©λ©λλ€.
- μ κ·Όμ λ°μ½λ μ΄ν°: getter λ° setter μ κ·Όμμ μ μ©λ©λλ€.
- μμ± λ°μ½λ μ΄ν°: ν΄λμ€ μμ±μ μ μ©λ©λλ€.
- λ§€κ°λ³μ λ°μ½λ μ΄ν°: λ©μλμ λ§€κ°λ³μμ μ μ©λ©λλ€.
ν΄λμ€ λ°μ½λ μ΄ν°
ν΄λμ€ λ°μ½λ μ΄ν°λ ν΄λμ€μ λμμ μμ νκ±°λ ν₯μμν€λ λ° μ¬μ©λ©λλ€. ν΄λμ€ μμ±μλ₯Ό μΈμλ‘ λ°μ μλ³Έμ λ체ν μλ‘μ΄ μμ±μλ₯Ό λ°νν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ λ‘κΉ , μμ‘΄μ± μ£Όμ λλ μν κ΄λ¦¬μ κ°μ κΈ°λ₯μ μΆκ°ν μ μμ΅λλ€.
μμ :
function loggable(constructor: Function) {
console.log("Class " + constructor.name + " was created.");
}
@loggable
class User {
name: string;
constructor(name: string) {
this.name = name;
}
}
const user = new User("Alice"); // μΆλ ₯: Class User was created.
μ΄ μμ μμ loggable λ°μ½λ μ΄ν°λ User ν΄λμ€μ μ μΈμ€ν΄μ€κ° μμ±λ λλ§λ€ μ½μμ λ©μμ§λ₯Ό κΈ°λ‘ν©λλ€. μ΄λ λλ²κΉ
μ΄λ λͺ¨λν°λ§μ μ μ©ν μ μμ΅λλ€.
λ©μλ λ°μ½λ μ΄ν°
λ©μλ λ°μ½λ μ΄ν°λ ν΄λμ€ λ΄ λ©μλμ λμμ μμ νλ λ° μ¬μ©λ©λλ€. λ€μκ³Ό κ°μ μΈμλ₯Ό λ°μ΅λλ€:
target: ν΄λμ€μ νλ‘ν νμ .propertyKey: λ©μλμ μ΄λ¦.descriptor: λ©μλμ μμ± λμ€ν¬λ¦½ν°.
λμ€ν¬λ¦½ν°λ₯Ό μ¬μ©νλ©΄ λ©μλμ λμμ μ κ·Όνκ³ μμ ν μ μμΌλ©°, μΆκ° λ‘μ§μΌλ‘ κ°μΈκ±°λ μμ ν μ¬μ μν μ μμ΅λλ€.
μμ :
function logMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling method ${propertyKey} with arguments: ${args}`);
const result = originalMethod.apply(this, args);
console.log(`Method ${propertyKey} returned: ${result}`);
return result;
};
return descriptor;
}
class Calculator {
@logMethod
add(a: number, b: number): number {
return a + b;
}
}
const calculator = new Calculator();
const sum = calculator.add(5, 3); // λ©μλ νΈμΆ λ° λ°ν κ°μ λν λ‘κ·Έ μΆλ ₯
μ΄ μμ μμ logMethod λ°μ½λ μ΄ν°λ λ©μλμ μΈμμ λ°ν κ°μ κΈ°λ‘ν©λλ€. μ΄λ λλ²κΉ
λ° μ±λ₯ λͺ¨λν°λ§μ μ μ©ν μ μμ΅λλ€.
μ κ·Όμ λ°μ½λ μ΄ν°
μ κ·Όμ λ°μ½λ μ΄ν°λ λ©μλ λ°μ½λ μ΄ν°μ μ μ¬νμ§λ§ getter λ° setter μ κ·Όμμ μ μ©λ©λλ€. λ©μλ λ°μ½λ μ΄ν°μ λμΌν μΈμλ₯Ό λ°μΌλ©° μ κ·Όμμ λμμ μμ ν μ μμ΅λλ€.
μμ :
function validate(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalSet = descriptor.set;
descriptor.set = function (value: any) {
if (value < 0) {
throw new Error("Value must be non-negative.");
}
originalSet.call(this, value);
};
}
class Temperature {
private _celsius: number;
constructor(celsius: number) {
this._celsius = celsius;
}
@validate
set celsius(value: number) {
this._celsius = value;
}
get celsius(): number {
return this._celsius;
}
}
const temperature = new Temperature(25);
temperature.celsius = 30; // μ ν¨ν¨
// temperature.celsius = -10; // μ€λ₯ λ°μ
μ΄ μμ μμ validate λ°μ½λ μ΄ν°λ μ¨λ κ°μ΄ μμκ° μλλλ‘ λ³΄μ₯ν©λλ€. μ΄λ λ°μ΄ν° 무결μ±μ κ°μ νλ λ° μ μ©ν μ μμ΅λλ€.
μμ± λ°μ½λ μ΄ν°
μμ± λ°μ½λ μ΄ν°λ ν΄λμ€ μμ±μ λμμ μμ νλ λ° μ¬μ©λ©λλ€. λ€μκ³Ό κ°μ μΈμλ₯Ό λ°μ΅λλ€:
target: ν΄λμ€μ νλ‘ν νμ (μΈμ€ν΄μ€ μμ±μ κ²½μ°) λλ ν΄λμ€ μμ±μ (μ μ μμ±μ κ²½μ°).propertyKey: μμ±μ μ΄λ¦.
μμ± λ°μ½λ μ΄ν°λ λ©νλ°μ΄ν°λ₯Ό μ μνκ±°λ μμ±μ λμ€ν¬λ¦½ν°λ₯Ό μμ νλ λ° μ¬μ©λ μ μμ΅λλ€.
μμ :
function readonly(target: any, propertyKey: string) {
Object.defineProperty(target, propertyKey, {
writable: false,
});
}
class Configuration {
@readonly
apiUrl: string = "https://api.example.com";
}
const config = new Configuration();
// config.apiUrl = "https://newapi.example.com"; // strict λͺ¨λμμ μ€λ₯ λ°μ
μ΄ μμ μμ readonly λ°μ½λ μ΄ν°λ apiUrl μμ±μ μ½κΈ° μ μ©μΌλ‘ λ§λ€μ΄ μ΄κΈ°ν ν μμ λμ§ μλλ‘ ν©λλ€. μ΄λ λΆλ³μ κ΅¬μ± κ°μ μ μνλ λ° μ μ©ν μ μμ΅λλ€.
λ§€κ°λ³μ λ°μ½λ μ΄ν°
λ§€κ°λ³μ λ°μ½λ μ΄ν°λ λ©μλ λ§€κ°λ³μμ λμμ μμ νλ λ° μ¬μ©λ©λλ€. λ€μκ³Ό κ°μ μΈμλ₯Ό λ°μ΅λλ€:
target: ν΄λμ€μ νλ‘ν νμ (μΈμ€ν΄μ€ λ©μλμ κ²½μ°) λλ ν΄λμ€ μμ±μ (μ μ λ©μλμ κ²½μ°).propertyKey: λ©μλμ μ΄λ¦.parameterIndex: λ©μλμ λ§€κ°λ³μ λͺ©λ‘μμ λ§€κ°λ³μμ μΈλ±μ€.
λ§€κ°λ³μ λ°μ½λ μ΄ν°λ λ€λ₯Έ μ νμ λ°μ½λ μ΄ν°λ³΄λ€ λ μ¬μ©λμ§λ§, μ λ ₯ λ§€κ°λ³μλ₯Ό κ²μ¦νκ±°λ μμ‘΄μ±μ μ£Όμ νλ λ° μ μ©ν μ μμ΅λλ€.
μμ :
function required(target: any, propertyKey: string, parameterIndex: number) {
const existingRequiredParameters: number[] = Reflect.getOwnMetadata(propertyKey, target, "required") || [];
existingRequiredParameters.push(parameterIndex);
Reflect.defineMetadata(propertyKey, existingRequiredParameters, target, "required");
}
function validateMethod(target: any, propertyName: string, descriptor: PropertyDescriptor) {
let method = descriptor.value!;
descriptor.value = function () {
let requiredParameters: number[] = Reflect.getOwnMetadata(propertyName, target, "required");
if (requiredParameters) {
for (let parameterIndex of requiredParameters) {
if (arguments[parameterIndex] === null || arguments[parameterIndex] === undefined) {
throw new Error(`Missing required argument at index ${parameterIndex}`);
}
}
}
return method.apply(this, arguments);
};
}
class ArticleService {
create(
@required title: string,
@required content: string
): void {
console.log(`Creating article with title: ${title} and content: ${content}`);
}
}
const service = new ArticleService();
// service.create("My Article", null); // μ€λ₯ λ°μ
service.create("My Article", "Article Content"); // μ ν¨ν¨
μ΄ μμ μμ required λ°μ½λ μ΄ν°λ λ§€κ°λ³μλ₯Ό νμλ‘ νμνκ³ , validateMethod λ°μ½λ μ΄ν°λ μ΄λ¬ν λ§€κ°λ³μκ° null λλ undefinedκ° μλμ§ νμΈν©λλ€. μ΄λ λ©μλ μ
λ ₯ μ ν¨μ± κ²μ¬λ₯Ό κ°μ νλ λ° μ μ©ν μ μμ΅λλ€.
λ©νλ°μ΄ν° νλ‘κ·Έλλ°κ³Ό λ°μ½λ μ΄ν°
λ°μ½λ μ΄ν°μ κ°μ₯ κ°λ ₯ν μ¬μ© μ¬λ‘ μ€ νλλ λ©νλ°μ΄ν° νλ‘κ·Έλλ°μ λλ€. λ©νλ°μ΄ν°λ λ°μ΄ν°μ λν λ°μ΄ν°μ λλ€. νλ‘κ·Έλλ° λ§₯λ½μμλ μ½λμ ꡬ쑰, λμ, λͺ©μ μ μ€λͺ νλ λ°μ΄ν°μ λλ€. λ°μ½λ μ΄ν°λ λ©νλ°μ΄ν°λ₯Ό ν΄λμ€, λ©μλ, μμ±, λ§€κ°λ³μμ μ°κ²°νλ κΉλνκ³ μ μΈμ μΈ λ°©λ²μ μ 곡ν©λλ€.
Reflect Metadata API
Reflect Metadata APIλ κ°μ²΄μ μ°κ΄λ λ©νλ°μ΄ν°λ₯Ό μ μ₯νκ³ κ²μν μ μλ νμ€ APIμ λλ€. λ€μκ³Ό κ°μ ν¨μλ₯Ό μ 곡ν©λλ€:
Reflect.defineMetadata(key, value, target, propertyKey): κ°μ²΄μ νΉμ μμ±μ λν λ©νλ°μ΄ν°λ₯Ό μ μν©λλ€.Reflect.getMetadata(key, target, propertyKey): κ°μ²΄μ νΉμ μμ±μ λν λ©νλ°μ΄ν°λ₯Ό κ²μν©λλ€.Reflect.hasMetadata(key, target, propertyKey): κ°μ²΄μ νΉμ μμ±μ λν λ©νλ°μ΄ν°κ° μλμ§ νμΈν©λλ€.Reflect.deleteMetadata(key, target, propertyKey): κ°μ²΄μ νΉμ μμ±μ λν λ©νλ°μ΄ν°λ₯Ό μμ ν©λλ€.
μ΄λ¬ν ν¨μλ₯Ό λ°μ½λ μ΄ν°μ ν¨κ» μ¬μ©νμ¬ μ½λ μμμ λ©νλ°μ΄ν°λ₯Ό μ°κ²°ν μ μμ΅λλ€.
μμ : λ©νλ°μ΄ν° μ μ λ° κ²μ
import 'reflect-metadata';
const logKey = "log";
function log(message: string) {
return function (target: any, key: string, descriptor: PropertyDescriptor) {
Reflect.defineMetadata(logKey, message, target, key);
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(Reflect.getMetadata(logKey, target, key));
const result = originalMethod.apply(this, args);
return result;
}
return descriptor;
}
}
class Example {
@log("Executing method")
myMethod(arg: string): string {
return `Method called with ${arg}`;
}
}
const example = new Example();
example.myMethod("Hello"); // μΆλ ₯: Executing method, Method called with Hello
μ΄ μμ μμ log λ°μ½λ μ΄ν°λ Reflect Metadata APIλ₯Ό μ¬μ©νμ¬ λ‘κ·Έ λ©μμ§λ₯Ό myMethod λ©μλμ μ°κ²°ν©λλ€. λ©μλκ° νΈμΆλλ©΄ λ°μ½λ μ΄ν°λ λ©μμ§λ₯Ό κ²μνμ¬ μ½μμ κΈ°λ‘ν©λλ€.
λ©νλ°μ΄ν° νλ‘κ·Έλλ°μ μ¬μ© μ¬λ‘
λ°μ½λ μ΄ν°λ₯Ό μ¬μ©ν λ©νλ°μ΄ν° νλ‘κ·Έλλ°μ λ€μκ³Ό κ°μ λ§μ μ€μ©μ μΈ μμ© λΆμΌκ° μμ΅λλ€:
- μ§λ ¬ν λ° μμ§λ ¬ν: μμ±μ λ©νλ°μ΄ν°λ₯Ό μ£ΌμμΌλ‘ λ¬μ JSONμ΄λ λ€λ₯Έ νμμΌλ‘ μ§λ ¬ν λλ μμ§λ ¬ννλ λ°©λ²μ μ μ΄ν©λλ€. μ΄λ μΈλΆ APIλ λ°μ΄ν°λ² μ΄μ€μ λ°μ΄ν°λ₯Ό λ€λ£° λ, νΉν λ€λ₯Έ νλ«νΌ κ°μ λ°μ΄ν° λ³νμ΄ νμν λΆμ° μμ€ν (μ: λ€λ₯Έ μ§μ νμ€ κ°μ λ μ§ νμ λ³ν)μμ μ μ©ν μ μμ΅λλ€. μλ₯Ό λ€μ΄ κ΅μ λ°°μ‘ μ£Όμλ₯Ό μ²λ¦¬νλ μ μ μκ±°λ νλ«νΌμμ λ©νλ°μ΄ν°λ₯Ό μ¬μ©νμ¬ κ° κ΅κ°μ λ§λ μ¬λ°λ₯Έ μ£Όμ νμκ³Ό μ ν¨μ± κ²μ¬ κ·μΉμ μ§μ ν μ μμ΅λλ€.
- μμ‘΄μ± μ£Όμ : λ©νλ°μ΄ν°λ₯Ό μ¬μ©νμ¬ ν΄λμ€μ μ£Όμ ν΄μΌ ν μμ‘΄μ±μ μλ³ν©λλ€. μ΄λ μμ‘΄μ± κ΄λ¦¬λ₯Ό λ¨μννκ³ λμ¨ν κ²°ν©μ μ΄μ§ν©λλ€. μλΉμ€λ€μ΄ μλ‘ μμ‘΄νλ λ§μ΄ν¬λ‘μλΉμ€ μν€ν μ²λ₯Ό μκ°ν΄λ³΄μμμ€. λ°μ½λ μ΄ν°μ λ©νλ°μ΄ν°λ ꡬμ±μ κΈ°λ°μΌλ‘ μλΉμ€ ν΄λΌμ΄μΈνΈλ₯Ό λμ μΌλ‘ μ£Όμ νμ¬ λ μ¬μ΄ νμ₯κ³Ό λ΄κ²°ν¨μ±μ κ°λ₯νκ² ν μ μμ΅λλ€.
- μ ν¨μ± κ²μ¬: μ ν¨μ± κ²μ¬ κ·μΉμ λ©νλ°μ΄ν°λ‘ μ μνκ³ λ°μ½λ μ΄ν°λ₯Ό μ¬μ©νμ¬ λ°μ΄ν°λ₯Ό μλμΌλ‘ κ²μ¦ν©λλ€. μ΄λ λ°μ΄ν° 무결μ±μ 보μ₯νκ³ μμ©κ΅¬ μ½λλ₯Ό μ€μ λλ€. μλ₯Ό λ€μ΄, κΈλ‘λ² κΈμ΅ μ ν리μΌμ΄μ μ λ€μν μ§μ κΈμ΅ κ·μ μ μ€μν΄μΌ ν©λλ€. λ©νλ°μ΄ν°λ μ¬μ©μμ μμΉμ λ°λΌ ν΅ν νμ, μΈκΈ κ³μ° λ° κ±°λ νλμ λν μ ν¨μ± κ²μ¬ κ·μΉμ μ μνμ¬ νμ§ λ²λ₯ μ€μλ₯Ό 보μ₯ν μ μμ΅λλ€.
- λΌμ°ν λ° λ―Έλ€μ¨μ΄: λ©νλ°μ΄ν°λ₯Ό μ¬μ©νμ¬ μΉ μ ν리μΌμ΄μ μ λΌμ°νΈμ λ―Έλ€μ¨μ΄λ₯Ό μ μν©λλ€. μ΄λ μ ν리μΌμ΄μ μ ꡬμ±μ λ¨μννκ³ μ μ§λ³΄μμ±μ λμ λλ€. μ μΈκ³μ λΆμ°λ μ½ν μΈ μ μ‘ λ€νΈμν¬(CDN)λ λ©νλ°μ΄ν°λ₯Ό μ¬μ©νμ¬ μ½ν μΈ μ νκ³Ό μ¬μ©μ μμΉμ λ°λΌ μΊμ± μ μ± κ³Ό λΌμ°ν κ·μΉμ μ μνμ¬ μ μΈκ³ μ¬μ©μμ μ±λ₯μ μ΅μ ννκ³ μ§μ° μκ°μ μ€μΌ μ μμ΅λλ€.
- κΆν λΆμ¬ λ° μΈμ¦: μν , κΆν λ° μΈμ¦ μꡬ μ¬νμ λ©μλ λ° ν΄λμ€μ μ°κ²°νμ¬ μ μΈμ 보μ μ μ± μ μ©μ΄νκ² ν©λλ€. μ¬λ¬ λΆμμ μμΉμ μ§μμ΄ μλ λ€κ΅μ κΈ°μ μ μμν΄λ³΄μμμ€. λ°μ½λ μ΄ν°λ μ¬μ©μμ μν , λΆμ λ° μμΉμ λ°λΌ μ κ·Ό μ μ΄ κ·μΉμ μ μνμ¬ κΆν μλ μ§μλ§ λ―Όκ°ν λ°μ΄ν°μ κΈ°λ₯μ μ κ·Όν μ μλλ‘ λ³΄μ₯ν μ μμ΅λλ€.
λͺ¨λ² μ¬λ‘
μλ°μ€ν¬λ¦½νΈ λ°μ½λ μ΄ν°λ₯Ό μ¬μ©ν λ λ€μ λͺ¨λ² μ¬λ‘λ₯Ό κ³ λ €νμμμ€:
- λ°μ½λ μ΄ν°λ λ¨μνκ² μ μ§: λ°μ½λ μ΄ν°λ μ§μ€μ μ΄μ΄μΌ νλ©°, λ¨μΌνκ³ μ μ μλ μμ μ μνν΄μΌ ν©λλ€. κ°λ μ±κ³Ό μ μ§λ³΄μμ±μ μ μ§νκΈ° μν΄ λ°μ½λ μ΄ν° λ΄μ 볡μ‘ν λ‘μ§μ νΌνμμμ€.
- λ°μ½λ μ΄ν° ν©ν 리 μ¬μ©: μ€μ κ°λ₯ν λ°μ½λ μ΄ν°λ₯Ό νμ©νκΈ° μν΄ λ°μ½λ μ΄ν° ν©ν 리λ₯Ό μ¬μ©νμμμ€. μ΄λ λ°μ½λ μ΄ν°λ₯Ό λ μ μ°νκ³ μ¬μ¬μ© κ°λ₯νκ² λ§λλλ€.
- λΆμ ν¨κ³Ό νΌνκΈ°: λ°μ½λ μ΄ν°λ μ£Όλ‘ λ°μ½λ μ΄νΈλ μμλ₯Ό μμ νκ±°λ λ©νλ°μ΄ν°λ₯Ό μ°κ²°νλ λ° μ€μ μ λμ΄μΌ ν©λλ€. μ½λλ₯Ό μ΄ν΄νκ³ λλ²κΉ νκΈ° μ΄λ ΅κ² λ§λ€ μ μλ 볡μ‘ν λΆμ ν¨κ³Όλ₯Ό λ°μ½λ μ΄ν° λ΄μμ μννμ§ λ§μμμ€.
- νμ μ€ν¬λ¦½νΈ μ¬μ©: νμ μ€ν¬λ¦½νΈλ νμ κ²μ¬ λ° μΈν 리μΌμ€λ₯Ό ν¬ν¨νμ¬ λ°μ½λ μ΄ν°μ λν νλ₯ν μ§μμ μ 곡ν©λλ€. νμ μ€ν¬λ¦½νΈλ₯Ό μ¬μ©νλ©΄ μ€λ₯λ₯Ό μ‘°κΈ°μ λ°κ²¬νκ³ κ°λ° κ²½νμ ν₯μμν¬ μ μμ΅λλ€.
- λ°μ½λ μ΄ν° λ¬Έμν: λ°μ½λ μ΄ν°μ λͺ©μ κ³Ό μ¬μ© λ°©λ²μ μ€λͺ νκΈ° μν΄ λͺ ννκ² λ¬Έμννμμμ€. μ΄λ λ€λ₯Έ κ°λ°μλ€μ΄ λ°μ½λ μ΄ν°λ₯Ό μ΄ν΄νκ³ μ¬λ°λ₯΄κ² μ¬μ©νλ κ²μ λ μ½κ² λ§λλλ€.
- μ±λ₯ κ³ λ €: λ°μ½λ μ΄ν°λ κ°λ ₯νμ§λ§ μ±λ₯μ μν₯μ μ€ μλ μμ΅λλ€. νΉν μ±λ₯μ΄ μ€μν μ ν리μΌμ΄μ μμλ λ°μ½λ μ΄ν°μ μ±λ₯ μν₯μ μΌλμ λμμμ€.
λ°μ½λ μ΄ν°λ₯Ό μ¬μ©ν κ΅μ ν μμ
λ°μ½λ μ΄ν°λ λ‘μΌμΌ νΉμ λ°μ΄ν°μ λμμ μ½λ κ΅¬μ± μμμ μ°κ²°νμ¬ κ΅μ ν(i18n) λ° νμ§ν(l10n)λ₯Ό μ§μν μ μμ΅λλ€:
μμ : νμ§νλ λ μ§ νμ μ§μ
import 'reflect-metadata';
interface DateFormatOptions {
locale: string;
options?: Intl.DateTimeFormatOptions;
}
const dateFormatKey = 'dateFormat';
function formatDate(options: DateFormatOptions) {
return function(target: any, propertyKey: string) {
Reflect.defineMetadata(dateFormatKey, options, target, propertyKey);
};
}
class Event {
@formatDate({ locale: 'fr-FR', options: { year: 'numeric', month: 'long', day: 'numeric' } })
startDate: Date;
constructor(startDate: Date) {
this.startDate = startDate;
}
getFormattedStartDate(): string {
const options: DateFormatOptions = Reflect.getMetadata(dateFormatKey, Object.getPrototypeOf(this), 'startDate');
return this.startDate.toLocaleDateString(options.locale, options.options);
}
}
const event = new Event(new Date());
console.log(event.getFormattedStartDate()); // νλμ€μ΄ νμμΌλ‘ λ μ§ μΆλ ₯
μμ : μ¬μ©μ μμΉ κΈ°λ° ν΅ν νμ μ§μ
import 'reflect-metadata';
interface CurrencyFormatOptions {
locale: string;
currency: string;
}
const currencyFormatKey = 'currencyFormat';
function formatCurrency(options: CurrencyFormatOptions) {
return function(target: any, propertyKey: string) {
Reflect.defineMetadata(currencyFormatKey, options, target, propertyKey);
};
}
class Product {
@formatCurrency({ locale: 'de-DE', currency: 'EUR' })
price: number;
constructor(price: number) {
this.price = price;
}
getFormattedPrice(): string {
const options: CurrencyFormatOptions = Reflect.getMetadata(currencyFormatKey, Object.getPrototypeOf(this), 'price');
return this.price.toLocaleString(options.locale, { style: 'currency', currency: options.currency });
}
}
const product = new Product(99.99);
console.log(product.getFormattedPrice()); // λ
μΌ μ λ‘ νμμΌλ‘ κ°κ²© μΆλ ₯
ν₯ν κ³ λ €μ¬ν
μλ°μ€ν¬λ¦½νΈ λ°μ½λ μ΄ν°λ μ§ννλ κΈ°λ₯μ΄λ©°, νμ€μ μμ§ κ°λ° μ€μ λλ€. ν₯ν κ³ λ €μ¬νμ λ€μκ³Ό κ°μ΅λλ€:
- νμ€ν: λ°μ½λ μ΄ν°μ λν ECMAScript νμ€μ μμ§ μ§ν μ€μ λλ€. νμ€μ΄ λ°μ ν¨μ λ°λΌ λ°μ½λ μ΄ν°μ λ¬Έλ²κ³Ό λμμ λ³κ²½μ΄ μμ μ μμ΅λλ€.
- μ±λ₯ μ΅μ ν: λ°μ½λ μ΄ν°κ° λ λ리 μ¬μ©λ¨μ λ°λΌ μ ν리μΌμ΄μ μ±λ₯μ λΆμ μ μΈ μν₯μ λ―ΈμΉμ§ μλλ‘ μ±λ₯ μ΅μ νκ° νμν κ²μ λλ€.
- λꡬ μ§μ: IDE ν΅ν© λ° λλ²κΉ λꡬμ κ°μ λ°μ½λ μ΄ν°μ λν ν₯μλ λꡬ μ§μμ κ°λ°μλ€μ΄ λ°μ½λ μ΄ν°λ₯Ό ν¨κ³Όμ μΌλ‘ μ¬μ©νλ κ²μ λ μ½κ² λ§λ€ κ²μ λλ€.
κ²°λ‘
μλ°μ€ν¬λ¦½νΈ λ°μ½λ μ΄ν°λ λ©νλ°μ΄ν° νλ‘κ·Έλλ°μ ꡬννκ³ μ½λμ λμμ ν₯μμν€λ κ°λ ₯ν λꡬμ λλ€. λ°μ½λ μ΄ν°λ₯Ό μ¬μ©νλ©΄ κΉλνκ³ μ μΈμ μ΄λ©° μ¬μ¬μ© κ°λ₯ν λ°©μμΌλ‘ κΈ°λ₯μ μΆκ°ν μ μμ΅λλ€. μ΄λ λ μ μ§λ³΄μνκΈ° μ½κ³ , ν μ€νΈνκΈ° μ¬μ°λ©°, νμ₯ κ°λ₯ν μ½λλ‘ μ΄μ΄μ§λλ€. λ€μν μ νμ λ°μ½λ μ΄ν°λ₯Ό μ΄ν΄νκ³ ν¨κ³Όμ μΌλ‘ μ¬μ©νλ κ²μ νλ μλ°μ€ν¬λ¦½νΈ κ°λ°μ νμμ μ λλ€. νΉν Reflect Metadata APIμ κ²°ν©λ λ°μ½λ μ΄ν°λ μμ‘΄μ± μ£Όμ λ° μ ν¨μ± κ²μ¬μμλΆν° μ§λ ¬ν λ° λΌμ°ν μ μ΄λ₯΄κΈ°κΉμ§ λ€μν κ°λ₯μ±μ μ΄μ΄μ£Όμ΄ μ½λλ₯Ό λ ννλ ₯ μκ³ κ΄λ¦¬νκΈ° μ½κ² λ§λλλ€.